#pragma once
// #ifndef _THREAD_HPP
// #define _THREAD_HPP

#include <iostream>
#include <string>
#include <pthread.h>
#include <cstdio>
#include <cstring>
#include <functional>
#include <unistd.h> //使用时要加上选项-pthread

using std::cin;
using std::cout;
using std::endl;

//pthread_create是C语言的接口，不兼容C++的写法
//包装一个函数指针（C++）
//typedef std::function<void (void*)> fun_t;
//通过typedef定义函数指针类型（C）
typedef void* (*fun_t)(void*);

//线程执行函数的参数
class ThreadData
{
public:
    void* sock_fd_; //要给线程函数要从线程池获取方法，先传入线程池
    void* sockaddr_in_; //要给线程函数要从线程池获取方法，先传入线程池
    std::string name_;
};


//线程类：简单把线程相关的数据和函数封装成一个类
class Thread
{
private:
    pthread_t tid_; //线程ID
    std::string name_; //线程名字
    ThreadData threaddata; //线程执行函数的参数(里面存放了线程名和线程池对象(用来找到任务队列))
    //用类的指针没有定义一个实体对象。

public:
    //一个线程需要对外提供的方法有哪些呢？
    //1.创建线程（封装一下pthread_create）
    Thread(int num, fun_t callback, void* sock_fd, void* sockaddrin) 
    {
        char nameBuffer[64] = {0};//线程的名字
        int s = snprintf(nameBuffer, sizeof(nameBuffer)-1, "Thread-%d", num);
        nameBuffer[s] = '\0';
        name_ = nameBuffer;

        threaddata.name_ = nameBuffer; //线程名
        threaddata.sock_fd_ = sock_fd; //客户端进程的socket_fd
        threaddata.sockaddr_in_ = sockaddrin; //服务器进程的sockaddr_in

        //1.创建线程（即线程启动：封装一下pthread_create）
        pthread_create(&tid_, nullptr, callback, &threaddata);
        cout << "线程：" << name_ << "，成功创建。" << endl;
    }

    ~Thread()
    {
        cout << "线程：" << name_ << "，成功释放。" << endl;
    }


    //2.等待子线程退出。（封装一下pthread_join）
    //能将等待子线程退出函数放到析构函数中吗？
    //最好不要，等待子线程函数最好是能被主动调用。
    void p_jion()
    {
        cout << "正在等待线程：" << name_ << "退出。" << endl;
        pthread_join(tid_, nullptr);
    }
    
    //3.获取线程名
    std::string getname()
    {
        return name_;
    }
};

//#endif